package io.github.echarts.model.series;

import io.github.echarts.model.SeriesModel;
import io.github.echarts.model.coordinate.CoordinateSystem;
import io.github.echarts.model.coordinate.DataRange;
import io.github.echarts.option.series.BarSeries;
import io.github.echarts.option.series.SeriesOption;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Collections;
import java.util.Arrays;

/**
 * 系列数据管理器
 * 负责管理所有系列数据，数据转换和堆叠计算，不涉及渲染逻辑
 */
public class SeriesDataManager {
    
    /** 所有系列数据模型 */
    private List<SeriesModel> seriesModels;
    
    /** 系列分组（按坐标系类型） */
    private Map<String, List<SeriesModel>> seriesGroups;
    
    /** 堆叠组映射 */
    private Map<String, List<SeriesModel>> stackMap;
    
    /** 数据范围映射 */
    private Map<String, DataRange> dataRanges;
    
    /** 默认坐标系ID */
    private String defaultCoordinateSystemId = "cartesian_1";
    
    /**
     * 构造函数
     */
    public SeriesDataManager() {
        this.seriesModels = new ArrayList<>();
        this.seriesGroups = new HashMap<>();
        this.stackMap = new HashMap<>();
        this.dataRanges = new HashMap<>();
    }
    
    /**
     * 设置默认坐标系ID
     * 
     * @param id 默认坐标系ID
     */
    public void setDefaultCoordinateSystemId(String id) {
        this.defaultCoordinateSystemId = id;
    }
    
    /**
     * 获取默认坐标系ID
     * 
     * @return 默认坐标系ID
     */
    public String getDefaultCoordinateSystemId() {
        return defaultCoordinateSystemId;
    }
    
    /**
     * 添加系列模型
     *
     * @param seriesModel 系列模型
     */
    public void addSeries(SeriesModel seriesModel) {
        seriesModels.add(seriesModel);
        
        // 按坐标系分组
        String coordinateSystemId = seriesModel.getCoordinateSystemId();
        if (coordinateSystemId != null) {
            seriesGroups.computeIfAbsent(coordinateSystemId, k -> new ArrayList<>()).add(seriesModel);
        }
        
        // 处理堆叠
        String stack = seriesModel.getStack();
        if (stack != null && !stack.isEmpty()) {
            stackMap.computeIfAbsent(stack, k -> new ArrayList<>()).add(seriesModel);
        }
    }
    
    /**
     * 初始化系列数据模型
     * 
     * @param seriesOptions 系列配置列表
     */
    public void initialize(SeriesOption[] seriesOptions) {
        // 清空现有数据
        seriesModels.clear();
        seriesGroups.clear();
        stackMap.clear();
        dataRanges.clear();
        
        // 根据配置创建系列模型
        if (seriesOptions != null) {
            for (int i = 0; i < seriesOptions.length; i++) {
                SeriesOption seriesOption = seriesOptions[i];
                SeriesModel seriesModel = createSeriesModel(seriesOption, i);
                if (seriesModel != null) {
                    addSeries(seriesModel);
                }
            }
        }
        
        // 处理数据
        processData();
    }
    
    /**
     * 创建系列模型
     * 
     * @param seriesOption 系列配置
     * @param index 系列索引
     * @return 系列模型
     */
    private SeriesModel createSeriesModel(SeriesOption seriesOption, int index) {
        // 根据系列类型创建不同的系列模型
        String type = seriesOption.getType();
        
        // 确定坐标系ID
        // 1. 首先检查配置中是否指定了坐标系ID
        String coordinateSystemId = null;
        
        if (seriesOption.getCoordinateSystem() != null) {
            // 如果配置指定了坐标系类型，创建对应的ID
            String coordinateSystemType = seriesOption.getCoordinateSystem();
            
            // 检查是否有指定索引
            Integer coordinateSystemIndex = seriesOption.getCoordinateSystemIndex();
            int csIndex = coordinateSystemIndex != null ? coordinateSystemIndex : 1;
            
            // 生成格式化的ID
            coordinateSystemId = coordinateSystemType.toLowerCase() + "_" + csIndex;
        } else {
            // 使用默认坐标系ID
            coordinateSystemId = defaultCoordinateSystemId;
            
            // 根据图表类型自动设置合适的坐标系类型
            if ("radar".equals(type)) {
                coordinateSystemId = "radar_1";
            } else if ("pie".equals(type) || "gauge".equals(type)) {
                coordinateSystemId = "polar_1";
            }
        }
        
        SeriesModel seriesModel = null;
        if ("bar".equals(type)) {
            // 创建柱状图系列模型
            seriesModel = new DefaultBarSeriesModel((BarSeries) seriesOption, coordinateSystemId);
        }
        // 添加其他图表类型的支持
        
        if (seriesModel != null) {
            seriesModel.setSeriesIndex(index);
        }
        
        return seriesModel;
    }
    
    /**
     * 从系列选项创建模型
     *
     * @param seriesOptions 系列选项列表
     */
    public void createSeriesFromOptions(List<SeriesOption> seriesOptions) {
        if (seriesOptions == null) {
            return;
        }
        
        SeriesOption[] optionsArray = seriesOptions.toArray(new SeriesOption[0]);
        initialize(optionsArray);
    }
    
    /**
     * 处理所有系列数据
     */
    public void processData() {
        // 处理每个系列的数据
        for (SeriesModel series : seriesModels) {
            series.processData();
        }
        
        // 处理堆叠数据
        processStackedData();
        
        // 计算数据范围
        calculateDataRanges();
    }
    
    /**
     * 处理堆叠数据
     */
    private void processStackedData() {
        // 处理每个堆叠组
        for (Map.Entry<String, List<SeriesModel>> entry : stackMap.entrySet()) {
            calculateStackValues(entry.getValue());
        }
    }
    
    /**
     * 计算堆叠值
     *
     * @param stackSeries 堆叠系列列表
     */
    private void calculateStackValues(List<SeriesModel> stackSeries) {
        // 堆叠计算逻辑
        if (stackSeries == null || stackSeries.isEmpty()) {
            return;
        }

        // 按Z轴高度和系列索引排序
        Collections.sort(stackSeries, (s1, s2) -> {
            // 首先按z轴层级排序
            int z1 = s1.getZLevel();
            int z2 = s2.getZLevel();
            if (z1 != z2) {
                return z1 - z2;
            }
            
            // z轴相同则按系列索引排序
            return s1.getSeriesIndex() - s2.getSeriesIndex();
        });

        // 确定数据长度（以第一个系列为准）
        SeriesModel firstSeries = stackSeries.get(0);
        List<Object> firstSeriesData = firstSeries.getData();
        if (firstSeriesData == null || firstSeriesData.isEmpty()) {
            return;
        }

        int dataLength = firstSeriesData.size();
        
        // 创建正负堆叠基准值数组（分别处理正值和负值的堆叠）
        double[] positiveStackValues = new double[dataLength];
        double[] negativeStackValues = new double[dataLength];
        
        // 初始化基准值为0
        Arrays.fill(positiveStackValues, 0);
        Arrays.fill(negativeStackValues, 0);

        // 逐个系列处理堆叠值
        for (SeriesModel series : stackSeries) {
            List<Object> seriesData = series.getData();
            if (seriesData == null) {
                continue;
            }
            
            // 获取实际数据长度（可能与第一个系列不同）
            int actualLength = Math.min(seriesData.size(), dataLength);
            
            // 创建当前系列的堆叠基准值
            double[] stackedBaseline = new double[dataLength];
            
            // 计算堆叠值
            for (int i = 0; i < actualLength; i++) {
                Object dataObj = seriesData.get(i);
                double value = 0;
                
                // 提取数值
                if (dataObj instanceof Number) {
                    value = ((Number) dataObj).doubleValue();
                } else if (dataObj instanceof Map) {
                    @SuppressWarnings("unchecked")
                    Object valueObj = ((Map<String, Object>) dataObj).get("value");
                    if (valueObj instanceof Number) {
                        value = ((Number) valueObj).doubleValue();
                    }
                } else {
                    try {
                        value = Double.parseDouble(dataObj.toString());
                    } catch (Exception e) {
                        // 忽略无法解析的值
                    }
                }
                
                // 根据值的正负选择基准值数组
                if (value >= 0) {
                    stackedBaseline[i] = positiveStackValues[i];
                    positiveStackValues[i] += value;
                } else {
                    stackedBaseline[i] = negativeStackValues[i];
                    negativeStackValues[i] += value; // 注意：负值是相加
                }
            }
            
            // 将堆叠基准值设置到系列模型中
            if (series instanceof BarSeriesModel) {
                ((DefaultBarSeriesModel) series).setStackedBaseline(stackedBaseline);
            }
        }
    }
    
    /**
     * 计算数据范围
     */
    public void calculateDataRanges() {
        // 按坐标系和系列类型计算数据范围
        for (Map.Entry<String, List<SeriesModel>> entry : seriesGroups.entrySet()) {
            String coordinateSystemId = entry.getKey();
            List<SeriesModel> seriesList = entry.getValue();
            
            // 计算该坐标系下的数据范围
            DataRange dataRange = calculateDataRangeForSeries(seriesList);
            dataRanges.put(coordinateSystemId, dataRange);
            
            // 更新关联的坐标系数据范围
            updateCoordinateSystemRange(coordinateSystemId, dataRange);
        }
    }
    
    /**
     * 计算一组系列的数据范围
     *
     * @param seriesList 系列列表
     * @return 数据范围
     */
    private DataRange calculateDataRangeForSeries(List<SeriesModel> seriesList) {
        // 简单实现：找出所有系列数据的最小值和最大值
        double min = Double.MAX_VALUE;
        double max = Double.MIN_VALUE;
        boolean hasData = false;
        
        for (SeriesModel series : seriesList) {
            DataRange range = series.getDataRange();
            if (range != null) {
                min = Math.min(min, range.getMin());
                max = Math.max(max, range.getMax());
                hasData = true;
            }
            
            // 对于堆叠图表，还要考虑堆叠后的总值
            if (series instanceof BarSeriesModel && ((BarSeriesModel) series).isStacked()) {
                DefaultBarSeriesModel barSeries = (DefaultBarSeriesModel) series;
                double[] baseline = barSeries.getStackedBaseline();
                
                if (baseline != null) {
                    List<Double> values = barSeries.getNumericData();
                    for (int i = 0; i < baseline.length && i < values.size(); i++) {
                        double stackedValue = baseline[i] + values.get(i);
                        max = Math.max(max, stackedValue);
                    }
                }
            }
        }
        
        // 确保有有效范围
        if (!hasData || min > max || min == Double.MAX_VALUE) {
            min = 0;
            max = 100;
        }
        
        // 确保正数据从0开始
        if (min > 0) {
            min = 0;
        }
        
        // 确保有足够的数据范围（避免min=max的情况）
        if (Math.abs(max - min) < 0.000001) {
            // 如果都是0，使用0-10
            if (max == 0) {
                max = 10;
            } else {
                // 否则扩展10%
                double delta = Math.abs(max * 0.1);
                min = min - delta;
                max = max + delta;
            }
        } else {
            // 正常情况，稍微扩展一点范围，使图表更美观
            double range = max - min;
            min = min - range * 0.05;
            max = max + range * 0.05;
        }
        
        return new DataRange(min, max);
    }
    
    /**
     * 更新坐标系的数据范围
     * 
     * @param coordinateSystemId 坐标系ID
     * @param dataRange 数据范围
     */
    private void updateCoordinateSystemRange(String coordinateSystemId, DataRange dataRange) {
        // 从每个系列中找到关联的坐标系
        for (SeriesModel series : seriesModels) {
            if (coordinateSystemId.equals(series.getCoordinateSystemId())) {
                CoordinateSystem cs = series.getCoordinateSystem();
                if (cs != null && cs instanceof io.github.echarts.model.coordinate.cartesian.DefaultCartesianCoordinateSystem) {
                    io.github.echarts.model.coordinate.cartesian.DefaultCartesianCoordinateSystem cartesian = 
                        (io.github.echarts.model.coordinate.cartesian.DefaultCartesianCoordinateSystem) cs;
                    
                    // 更新坐标系的数据范围
                    cartesian.setDataRange(dataRange);
                    
                    // 只需要更新一次即可
                    break;
                }
            }
        }
    }
    
    /**
     * 获取数据范围
     * 
     * @param coordinateSystemId 坐标系ID
     * @return 数据范围
     */
    public DataRange getDataRange(String coordinateSystemId) {
        return dataRanges.getOrDefault(coordinateSystemId, new DataRange(0, 100));
    }
    
    /**
     * 获取所有系列模型
     * 
     * @return 系列模型列表
     */
    public List<SeriesModel> getSeriesModels() {
        return seriesModels;
    }
    
    /**
     * 获取特定类型的系列模型
     * 
     * @param type 系列类型
     * @return 符合类型的系列模型列表
     */
    public List<SeriesModel> getSeriesByType(String type) {
        List<SeriesModel> result = new ArrayList<>();
        for (SeriesModel series : seriesModels) {
            if (series.getType().equals(type)) {
                result.add(series);
            }
        }
        return result;
    }
    
    /**
     * 获取指定坐标系的系列模型
     * 
     * @param coordinateSystemId 坐标系ID
     * @return 系列模型列表
     */
    public List<SeriesModel> getSeriesByCoordinateSystem(String coordinateSystemId) {
        return seriesGroups.getOrDefault(coordinateSystemId, new ArrayList<>());
    }
} 